package com.centling.smartSealForPhone.fragment;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.centling.smartSealForPhone.BuildConfig;
import com.centling.smartSealForPhone.R;
import com.centling.smartSealForPhone.activity.TitleBarActivity;
import com.centling.smartSealForPhone.constants.UserType;
import com.centling.smartSealForPhone.db.UpWarnInfo;
import com.centling.smartSealForPhone.application.SmartSeal;
import com.centling.smartSealForPhone.constants.GlobalData;
import com.centling.smartSealForPhone.constants.SPConstants;
import com.centling.smartSealForPhone.constants.UrlConstants;
import com.centling.smartSealForPhone.db.DbControl;
import com.centling.smartSealForPhone.utils.SPUtil;
import com.wsdk.service.BluetoothLeService;
import com.centling.smartSealForPhone.utils.BlueToothScanUtil;
import com.centling.smartSealForPhone.utils.ControlUtil;
import com.centling.smartSealForPhone.utils.OkHttpUtil;
import com.centling.smartSealForPhone.utils.ParseBluetoothData;
import com.centling.smartSealForPhone.utils.ShowDialog;
import com.centling.smartSealForPhone.utils.ShowToast;

import org.json.JSONException;
import org.json.JSONObject;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * @author fionera
 */
public class StampOriginActivity
        extends TitleBarActivity
        implements BlueToothScanUtil.StopSearchListener {

    private static final int OPEN_BLUE_DIALOG = 1000;

    private ImageView ivStamp;
    private TextView tvTimes;
    private Button ivStopStamp;

    private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
                mProcessDialog.dismiss();
                if (BuildConfig.DEBUG) {
                    ShowToast.shortTime("Stamp Time Connected");
                }
                GlobalData.isConnect = true;
            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
                ShowToast.shortTime("蓝牙已断开，请重新连接后完成用印");
                enableStampOperation();
            } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
                byte[] data = intent.getByteArrayExtra(BluetoothLeService.EXTRA_DATA);
                if (ParseBluetoothData.parseOpenByte(data) == 0x00) {
                    ShowToast.shortTime("可以用印");
                } else if (ParseBluetoothData.parseOpenByte(data) == 0xec) {
                    ShowToast.shortTime("请先将信印复位");
                    enableStampOperation();
                } else if (ParseBluetoothData.parseOpenByte(data) == 0xeb) {
                    GlobalData.hasAlarm = true;
                    // 上传报警信息
                    toUploadAlertTime(data);
                } else if(ParseBluetoothData.parseOpenByte(data) == 0xf4){
                    ShowToast.shortTime("开锁错误");
                    sendRequestToRollbackStamp();
                } else if (ParseBluetoothData.parseDeleteAlert(data)) {
                    GlobalData.hasAlarm = false;
                    new ControlUtil().stamp();
                } else if (data[3] == 0x0f && data[4] != 0x00) {
                    ShowToast.shortTime("开锁失败");
                    sendRequestToRollbackStamp();
                } else if (ParseBluetoothData.isStampReturn(data)) {
                    if (ParseBluetoothData.parseStampReturn(data) == 0x00||
                            ParseBluetoothData.parseStampReturn(data) == 0x04) {
                        // need deal with duplicated put in
                        if (!recordIds.contains(sealRecordId)) {
                            recordIds.add(sealRecordId);
                        }
                        enableStampOperation();
                        if(ParseBluetoothData.parseStampReturn(data) == 0x04){
                            DbControl.getInstance().insertWarningData("0", sealApplyId,
                                    String.valueOf(ParseBluetoothData.parseStampReturn(data)),
                                    String.valueOf(latitude), String.valueOf(longitude),
                                    locationName);
                        }
                        if (remainTimes == 0) {
                            ivStopStamp.setVisibility(View.GONE);
                        }
                        sendRequestWithResultToStamp();
                    } else if (ParseBluetoothData.parseStampReturn(data) == (byte) 0xff) {
                        ShowToast.shortTime("用印失败");
                        enableStampOperation();
                    } else {
                        ShowToast.shortTime("用印异常");
                        enableStampOperation();

                        DbControl.getInstance().insertWarningData("0", sealApplyId,
                                String.valueOf(ParseBluetoothData.parseStampReturn(data)),
                                String.valueOf(latitude), String.valueOf(longitude),
                                locationName);
                    }
                } else if (ParseBluetoothData.isGetSN(data)) {
                    byte[] fetchSn = new byte[15];
                    System.arraycopy(data, 5, fetchSn, 0, 15);
                    sn = ParseBluetoothData.bytesToSn(fetchSn);
                    if (remainTimes > 0) {
                        if (longitude == null || latitude == null || locationName == null) {
                            ShowToast.shortTime("获取定位信息失败\n请重新操作或重启章务通");
                            return;
                        }
                        hasAuthority = true;
                        disableStampOperation();
                        sendRequestToStamp();
                    } else {
                        ShowToast.shortTime("剩余次数为0，不能用印");
                    }
                }
            }
        }
    };

    private boolean hasAuthority = false;
    private String sealApplyId;
    private String sealRecordId;
    private String rollbackKey;
    private int remainTimes;

    private BlueToothScanUtil blueToothScanUtil;

    private ArrayList<String> recordIds = new ArrayList<>();

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_stamp_count_limit);

        Bundle bundle = getIntent().getExtras();
        if (bundle != null) {
            sealApplyId = bundle.getString("sealApplyId");
            macAddress = bundle.getString("macAddress");
            sn = bundle.getString("equipSn");
        }

        if (BuildConfig.DEBUG) {
            ShowToast.shortTime(macAddress);
        }

        setTitleBarText("限次用印");

        initView(getWindow().getDecorView());
        initBroadCast();

        blueToothScanUtil = new BlueToothScanUtil(mContext);
    }

    private void initBroadCast() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
        mContext.registerReceiver(bluetoothReceiver, intentFilter);
    }

    private void initView(View view) {
        view.setFocusable(true);
        view.setFocusableInTouchMode(true);
        view.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (keyCode == KeyEvent.KEYCODE_BACK) {
                        clickToBack();
                        return true;
                    }
                }
                return false;
            }
        });

        ivStamp = view.findViewById(R.id.iv_stamp_times_stamp);
        ivStamp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                clickToStamp();
            }
        });

        tvTimes = view.findViewById(R.id.tv_stamp_times_times);

        ivStopStamp= view.findViewById(R.id.iv_stamp_stop_stamp);
        ivStopStamp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                clickToStopStamp();
            }
        });

        TextView tvExit = view.findViewById(R.id.tv_stamp_times_exit);
        tvExit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                clickToBack();
            }
        });

        sendRequestToGetTimes(sealApplyId);
    }

    private void enableStampOperation() {
        ivStamp.setImageDrawable(
                ContextCompat.getDrawable(mContext, R.mipmap.prints));
        ivStamp.setClickable(true);
        tvTimes.setText(
                String.format(Locale.CHINA, "可申请授权: %d 次", remainTimes));
    }

    private void disableStampOperation() {
        ivStamp.setImageDrawable(ContextCompat.getDrawable(mContext, R.mipmap.prints1));
        ivStamp.setClickable(false);
    }

    private void clickToStamp() {
        if (!BlueToothScanUtil.isBlueToothOpened()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, OPEN_BLUE_DIALOG);
            return;
        }
        if (GlobalData.isConnect) {
            if ("0".equals(GlobalData.selfCheckStatus)) {
                if (!GlobalData.hasAlarm) {
                    new ControlUtil().getSN();
                } else {
                    disableStampOperation();
                    new ControlUtil().stamp();
                }
            } else {
                ShowToast.shortTime("设备异常，请联系管理员");
            }
        } else {
            /*
              not connected
             */
            ShowDialog.showSelectDialog(mContext, "重新连接蓝牙", "蓝牙未连接，请先连接蓝牙", "",
                    new View.OnClickListener() {

                        @Override
                        public void onClick(View v) {
                            mProcessDialog.setTitle("正在连接蓝牙").showNormal();
                            blueToothScanUtil.setMacAddress(macAddress);
                            blueToothScanUtil.startSearchBlueDevice();
                            blueToothScanUtil.setStopSearchListener(StampOriginActivity.this);
                        }
                    });
        }
    }

    private void clickToStopStamp(){
        ShowDialog.showSelectDialog(mContext, "警告", "确定将结束用印，剩余次数无法使用", "", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Map<String, String> param = new HashMap<>();
                param.put("sealApplyId", sealApplyId);
                postJsonEnqueue(UrlConstants.STOP_STAMP, param, new OkHttpUtil.NetCallBack() {
                    @Override
                    public void onSucceed(String json) {
                        clickToBack();
                    }

                    @Override
                    public void onFailed(String reason) {
                        ShowToast.shortTime("提前结束用印失败，请重试");
                    }
                });
            }
        });
    }

    private void clickToBack() {
        if (!hasAuthority) {
            mActivity.finish();
        } else {
            Bundle bundle = new Bundle();
            bundle.putString("applyId", sealApplyId);
            bundle.putStringArrayList("recordIds", recordIds);
            startActivity(new Intent(mContext, StampImgActivity.class).putExtras(bundle));
            mActivity.finish();
        }
    }

    /**
     * 上传报警起止时间
     */
    private void toUploadAlertTime(byte[] data){
        byte[] startTime = new byte[7];
        System.arraycopy(data, 5, startTime, 0, 7);
        byte[] endTime = new byte[7];
        System.arraycopy(data, 12, endTime, 0, 7);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
        try {
            Date dateStart = simpleDateFormat.parse(ControlUtil.bytesToHexString(startTime));
            Date dateEnd = simpleDateFormat.parse(ControlUtil.bytesToHexString(endTime));
            Map<String, String> params = new HashMap<>(10);
            params.put("processFlag", "0");
            params.put("ascSn", sn);
            params.put("alarmTimeStart", String.valueOf(dateStart.getTime()));
            params.put("alarmTimeEnd", String.valueOf(dateEnd.getTime()));
            params.put("latitude", String.valueOf(latitude));
            params.put("longitude", String.valueOf(longitude));
            params.put("alarmLocation", locationName);
            params.put("companyCode", SmartSeal.getInstance().getIp());
            postJsonEnqueue(UrlConstants.UPLOAD_ALERT, params, new OkHttpUtil.NetCallBack() {
                @Override
                public void onSucceed(String json) {
                    new ControlUtil().deleteAlert();
                }

                @Override
                public void onFailed(String reason) {
                    if ("没有找到用印记录".equals(reason)) {
                        new ControlUtil().deleteAlert();
                    }
                    enableStampOperation();
                }
            });
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    private void sendRequestToGetTimes(String id) {
        mProcessDialog.setTitle("正在获取用印次数").showNormal();
        getEnqueue(String.format(Locale.CHINA, UrlConstants.GET_STAMP_REMAIN_TIMES_NEW, id),
                new OkHttpUtil.NetCallBack() {
                    @Override
                    public void onSucceed(String json) {
                        mProcessDialog.dismiss();

                        try {
                            JSONObject object = new JSONObject(json);
                            remainTimes = Integer.parseInt(object.optString("remainTimes"));
                            tvTimes.setText(String.format(Locale.CHINA, "可申请授权: %d 次", remainTimes));
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }

                        if (!GlobalData.isConnect) {
                            mProcessDialog.setTitle("正在连接蓝牙").showNormal();
                            blueToothScanUtil.setMacAddress(macAddress);
                            blueToothScanUtil.startSearchBlueDevice();
                            blueToothScanUtil.setStopSearchListener(StampOriginActivity.this);
                        }
                    }

                    @Override
                    public void onFailed(String reason) {
                        mProcessDialog.dismiss();
                        ShowToast.shortTime(reason);
                        mActivity.finish();
                    }
                });
    }

    private void sendRequestToStamp() {
        Map<String, String> params = new HashMap<>();
        params.put("sealApplyId", sealApplyId);
        params.put("longtitude", String.valueOf(longitude));
        params.put("latitude", String.valueOf(latitude));
        params.put("locationName", locationName);
        params.put("authorityTimes", String.valueOf(remainTimes));
        postJsonEnqueue(UrlConstants.STAMP, params, new OkHttpUtil.NetCallBack() {
            @Override
            public void onSucceed(String json) {
                try {
                    JSONObject object = new JSONObject(json);
                    remainTimes = Integer.parseInt(object.optString("remainTimes"));
                    sealApplyId = object.optString("sealApplyId");
                    sealRecordId = object.optString("sealRecordId");
                    rollbackKey = object.optString("rollbackKey");

                    new ControlUtil().stamp();

                    tvTimes.setText(
                            String.format(Locale.CHINA, "一次授权已下发\n可申请授权: %d 次", remainTimes));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailed(String reason) {
                ShowToast.shortTime(reason);
                hasAuthority = false;
                ivStamp.setImageDrawable(ContextCompat.getDrawable(mContext, R.mipmap.prints));
                ivStamp.setClickable(true);
            }
        });
    }

    private void sendRequestWithResultToStamp() {
        Map<String, String> param = new HashMap<>();
        param.put("sealRecordId", sealRecordId);
        postJsonEnqueue(UrlConstants.STAMP_RESULT, param, new OkHttpUtil.NetCallBack() {
            @Override
            public void onSucceed(String json) {
                ShowToast.shortTime("盖章结果已上报");
            }

            @Override
            public void onFailed(String reason) {
                ShowToast.shortTime(reason);
            }
        });
    }

    private void sendRequestToRollbackStamp() {
        mProcessDialog.setTitle("正在回滚授权").showNormal();
        Map<String, String> param = new HashMap<>();
        param.put("sealRecordId", sealRecordId);
        param.put("rollbackKey", rollbackKey);
        postJsonEnqueue(UrlConstants.STAMP_ROLLBACK, param, new OkHttpUtil.NetCallBack() {
            @Override
            public void onSucceed(String json) {
                mProcessDialog.dismiss();
                try {
                    JSONObject jsonObject = new JSONObject(json);
                    remainTimes = Integer.parseInt(jsonObject.optString("remainTimes"));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                enableStampOperation();
            }

            @Override
            public void onFailed(String reason) {
                mProcessDialog.dismiss();
                ShowDialog.showSelectDialog(mContext, "回滚失败", "回滚失败，是否重试", "取消回滚将视为放弃本次用印",
                        new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                sendRequestToRollbackStamp();
                            }
                        }, new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                enableStampOperation();
                            }
                        });
            }
        });
    }

    private void sendRequestWithResultToAlert(byte errorFlag) {
        Map<String, String> param = new HashMap<>();
        param.put("processId", sealApplyId);
        param.put("processFlag", "0");
        param.put("alarmMsg", String.format(Locale.CHINA, "非法用印 %x", errorFlag));
        postJsonEnqueue(UrlConstants.STAMP_ALERT, param, new OkHttpUtil.NetCallBack() {
            @Override
            public void onSucceed(String json) {
            }

            @Override
            public void onFailed(String reason) {
            }
        });
    }

    private Double longitude = null;
    private Double latitude = null;
    private String locationName = null;

    // 高德地图
    private AMapLocationClient mLocationClient = null;
    private AMapLocationClientOption mLocationOption = null;
    private AMapLocationListener aMapLocationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation amapLocation) {
            if (amapLocation != null) {
                if (amapLocation.getErrorCode() == 0) {
                    longitude = amapLocation.getLongitude();
                    latitude = amapLocation.getLatitude();
                    locationName = amapLocation.getAddress();
                } else {
                    Log.e("AmapError", "location Error, ErrCode:"
                            + amapLocation.getErrorCode() + ", errInfo:"
                            + amapLocation.getErrorInfo());
                }
            }
        }
    };

    private void initLocation() {
        mLocationClient = new AMapLocationClient(mContext);
        mLocationClient.setLocationOption(getAMapDefaultLocationOption());
        mLocationClient.setLocationListener(aMapLocationListener);
        mLocationClient.startLocation();
    }

    public AMapLocationClientOption getAMapDefaultLocationOption() {
        if (mLocationOption == null) {
            mLocationOption = new AMapLocationClientOption();
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            mLocationOption.setNeedAddress(true);
            mLocationOption.setInterval(3000);
            mLocationOption.setKillProcess(true);
        }
        return mLocationOption;
    }

    @Override
    public void onResume() {
        super.onResume();
        if (!BlueToothScanUtil.isBlueToothOpened()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, OPEN_BLUE_DIALOG);
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        initLocation();
    }

    @Override
    public void onStop() {
        super.onStop();
        mLocationClient.unRegisterLocationListener(aMapLocationListener);
        if (mLocationClient != null && mLocationClient.isStarted()) {
            mLocationClient.stopLocation();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mLocationClient.onDestroy();
        mContext.unregisterReceiver(bluetoothReceiver);
        if(TextUtils.equals(UserType.EQUIP_COMMON_USER,
                SPUtil.getString(SPConstants.USER_TYPE))) {
            BluetoothLeService.disconnect();
        }
        UpWarnInfo.upgrandWarnInfo();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == OPEN_BLUE_DIALOG && resultCode == Activity.RESULT_CANCELED) {
            mActivity.finish();
        }
    }

    @Override
    public void onStopped(boolean timeout) {
        mProcessDialog.dismiss();
        if (timeout) {
            ShowToast.shortTime("连接设备失败");
        }
    }
}
